package com.cictec.middleware.elasticsearch.service.impl;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.cictec.middleware.commons.utils.DateUtils;
import com.cictec.middleware.commons.utils.PMSUtils;
import com.cictec.middleware.commons.utils.PropertiesUtils;
import com.cictec.middleware.commons.utils.elasticsearch.ESClientUtils;
import com.cictec.middleware.commons.utils.elasticsearch.ESModel;
import com.cictec.middleware.elasticsearch.service.ElasticsearchPositionService;
import com.fasterxml.jackson.core.JsonProcessingException;

/**
 * 中间件ES操作实现类，通过elasticsearch client实现
 * 
 * @author ql
 */
@SuppressWarnings("rawtypes")
@Service
public class ElasticsearchPositionServiceImpl implements ElasticsearchPositionService {

	private static Logger logger = LoggerFactory.getLogger(ElasticsearchPositionServiceImpl.class);

	/**
	 * 保存进出站信息
	 */
	@Override
	public void saveEnterOutStation(Map map) {
		// TODO Auto-generated method stub
		ESModel model = JSON.parseObject(JSON.toJSONString(map), ESModel.class);
		try {
			ESClientUtils.addDocument(model);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 批量写保存进出站信息
	 */
	@Override
	public void saveEnterOutStations(List<Map> list, Map additionalParams){
		try {
			String tableIndex = PropertiesUtils.getString("elasticsearch.index.enterout");
			List<ESModel> eSModelList = new ArrayList<ESModel>();
			for (Map map : list) {
				String id = DateUtils.formatDate(new Date(), "yyyyMMdd")+PMSUtils.getUUID();
				String tableType = PMSUtils.isNull(map.get("bus_plate_number")) + "-enterOut";	// type 为车牌号
				
				ESModel model = new ESModel();
				model.setId(id);
				model.setIndex(tableIndex);
				model.setType(tableType);	// type 类型为车牌号
				model.setJsonString(JSON.toJSONString(map));
				eSModelList.add(model);
			}
			ESClientUtils.addDocumentList(eSModelList);
		} catch (UnknownHostException e) {
			e.printStackTrace();
			logger.debug("保存ES 批量实时进出站信息错误：{}", e);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
			logger.debug("保存ES 批量实时进出站信息错误：{}", e);
		}
	}

	@Override
	public void savePosition(List<Map> list, Map additionalParams) {
		
		try {
			String esIndex = PropertiesUtils.getString("elasticsearch.index.position");
			String busNumber = PMSUtils.isNull(additionalParams.get("busNumber"));
			List<ESModel> eSModelList = new ArrayList<ESModel>();
			for (Map map : list) {

				
				String id = DateUtils.formatDate(new Date(), "yyyyMMdd")+PMSUtils.getUUID();
				
				ESModel model = new ESModel();
				model.setId(id);
				model.setIndex(esIndex);
				model.setType(busNumber);	// type 类型为车牌号
				model.setJsonString(JSON.toJSONString(map));
				eSModelList.add(model);
			}
			ESClientUtils.addDocumentList(eSModelList);
		} catch (UnknownHostException e) {
			e.printStackTrace();
			logger.debug("保存ES 批量位置信息错误：{}", e);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
			logger.debug("保存ES 批量位置信息错误：{}", e);
		}

	}


	@Override
	public List queryEnterOutStation(String date, String busNumber) {
		try {
			return queryEnterOutStation(date, null, null, busNumber, null, null, null);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return new ArrayList();
	}
	
	@Override
	public List queryEnterOutStation(Date startTime, Date endTime, String busNumber, String lineUuid, String lineType, String lsUuid) {
		try {
			return queryEnterOutStation(null, startTime, endTime, busNumber, lineUuid, lineType, lsUuid);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return new ArrayList();
	}

	
	private List<ESModel> queryEnterOutStation(String date, Date startTime, Date endTime, String busNumber, String lineUuid, String lineType, String lsUuid) {
		String tableIndex = PropertiesUtils.getString("elasticsearch.index.enterout");
//		String tableIndex = "bus-enteroutstation";
		String tableType = busNumber + "-enterOut";

		List<ESModel> dataList = new ArrayList<ESModel>();
		try {
			Client client = ESClientUtils.getClient();
			if (!ESClientUtils.isExistsType(tableIndex, tableType)) {
				return new ArrayList<ESModel>();
			}
			
			
//		QueryBuilder queryBuilder;
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		if(date != null) boolQueryBuilder.must(QueryBuilders.termQuery("date", date));
		if(busNumber != null) boolQueryBuilder.must(QueryBuilders.termQuery("bus_plate_number", busNumber));
		if(lineUuid != null) boolQueryBuilder.must(QueryBuilders.termQuery("line_uuid", lineUuid));
		if(lineType != null) boolQueryBuilder.must(QueryBuilders.termQuery("line_type", lineType));
		if(lsUuid != null) boolQueryBuilder.must(QueryBuilders.termQuery("ls_uuid", lsUuid));
			
//		if(startTime != null && endTime != null) boolQueryBuilder.must(QueryBuilders.rangeQuery("enter_time").from(startTime.getTime()).to(endTime.getTime());
			
			
			
			SearchResponse response = client.prepareSearch(tableIndex)
					.setTypes(tableType)
					.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
					.setQuery(boolQueryBuilder)
					.setSize(10000)
					.execute()
					.actionGet();
			//获取命中数
			//		System.out.println(response.getHits().totalHits());
			//获取响应字符串
			//		System.out.println(response.toString());
			//遍历查询结果输出相关度分值和文档内容
			SearchHits searchHits =  response.getHits();
			
			dataList = new ArrayList<>();
			ESModel model = null;
			for (SearchHit searchHit : searchHits) {
//				System.out.println(searchHit.getScore());
//				System.out.println(searchHit.getSourceAsString());
				String json = searchHit.getSourceAsString();

				model = new ESModel();
				model.setId(searchHit.getId());
				model.setIndex(tableIndex);
				model.setType(tableType);
				model.setJsonString(json);

				dataList.add(model);
			}
			
			client.close();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return dataList;
	}
	

	@Override
	public void deleteEnterOut(String date, String busNumber) {
		List<ESModel> oldEnterList = queryEnterOutStation(date, busNumber);	// 默认是10000条数据
		if(oldEnterList.size() > 0){
			logger.debug("删除es进出站信息：{} {}",date, busNumber);
			try {
				ESClientUtils.deleteIndex(oldEnterList);
			} catch (UnknownHostException e) {
				e.printStackTrace();
			}
		}

	}

	@Override
	public void deletePosition(String date, String busUuid, String busNumber) {
		// TODO Auto-generated method stub
		List<ESModel> esModelList =  _queryPosition(DateUtils.getStartDateTime(date), DateUtils.getEndDateTime(date), busUuid, busNumber, null, null);
		
		try {
			if(esModelList.size() > 0){
				ESClientUtils.deleteIndex(esModelList);
				
				if(esModelList.size() == 10000){
					esModelList = _queryPosition(DateUtils.getStartDateTime(date), DateUtils.getEndDateTime(date), busUuid, busNumber, null, null);	// 默认是10000条数据
					if(esModelList.size() > 0){
						ESClientUtils.deleteIndex(esModelList);
					}
				}
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		
		
	}

	@Override
	public List queryPosition(Date startTime, Date endTime, String busUuid, String busNumber, String lineUuid, String lineType) {
		
		List<ESModel> list =  _queryPosition(startTime, endTime, busUuid, busNumber, lineUuid, lineType);
		List rtlist = new ArrayList();
		for (ESModel esModel : list) {
			rtlist.add(JSON.parseObject(esModel.getJsonString(), Map.class));
		}
		return rtlist;
	}
	
	private List<ESModel> _queryPosition(Date startTime, Date endTime, String busUuid, String busNumber, String lineUuid, String lineType) {
		String tableIndex = PropertiesUtils.getString("elasticsearch.index.position");
		String tableType = busNumber;

		List<ESModel> dataList = new ArrayList<>();
		try {
			if(!ESClientUtils.isExistsType(tableIndex, tableType)){
				return new ArrayList<ESModel>();
			}
			
			Client client = ESClientUtils.getClient();
			if (!ESClientUtils.isExistsType(tableIndex, tableType)) {
				return new ArrayList<ESModel>();
			}

			BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
			
			if(lineUuid != null) boolQueryBuilder.must(QueryBuilders.termQuery("lineUuid", lineUuid));
			if(busUuid != null) boolQueryBuilder.must(QueryBuilders.termQuery("busUuid", busUuid));
			if(startTime != null && endTime != null) boolQueryBuilder.must(QueryBuilders.rangeQuery("gatherTime").from(startTime.getTime()).to(endTime.getTime()));
			
			
			
			SearchResponse response = client.prepareSearch(tableIndex)
					.setTypes(tableType)
					.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
					.setQuery(boolQueryBuilder)
					.setSize(10000)
					.execute()
					.actionGet();
			//获取命中数
//			System.out.println(response.getHits().totalHits());
			//获取响应字符串
//			System.out.println(response.toString());
			//遍历查询结果输出相关度分值和文档内容
			SearchHits searchHits =  response.getHits();
			

			ESModel model = null;
			for(SearchHit searchHit : searchHits){
//	        System.out.println(searchHit.getScore());
//	        System.out.println(searchHit.getSourceAsString());
				String json = searchHit.getSourceAsString();
				
				model = new ESModel();
				model.setId(searchHit.getId());
				model.setIndex(tableIndex);
				model.setType(tableType);
				model.setJsonString(json);
				
				dataList.add(model);
			}
			
			client.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return dataList;
	}

	@Override
	public void saveTimingPointTM(List<Map> list) {
		// TODO Auto-generated method stub
		try {
			String esIndex = PropertiesUtils.getString("elasticsearch.index.position");
			List<ESModel> eSModelList = new ArrayList<ESModel>();
			for (Map map : list) {

				
				String id = DateUtils.formatDate(new Date(), "yyyyMMdd")+PMSUtils.getUUID();
				String busNumber = PMSUtils.isNull(map.get("busNumber"));
				
				ESModel model = new ESModel();
				model.setId(id);
				model.setIndex(esIndex);
				model.setType(busNumber);	// type 类型为车牌号
				model.setJsonString(JSON.toJSONString(map));
				eSModelList.add(model);
			}
			ESClientUtils.addDocumentList(eSModelList);
		} catch (UnknownHostException e) {
			e.printStackTrace();
			logger.debug("保存ES 批量位置信息错误：{}", e);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
			logger.debug("保存ES 批量位置信息错误：{}", e);
		}
	}

	@Override
	public List queryTimingPointTM(Date startTime, Date endTime, String devCode, String lineUuid) {
		// TODO Auto-generated method stub
		return null;
	}

}
